package be.kuleuven.mume.social.twitter;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import be.kuleuven.mume.TwitterConst;
import be.kuleuven.mume.beans.PersoonBean;
import be.kuleuven.mume.exceptions.UserNotLoggedInException;
import be.kuleuven.mume.query.PersoonQuery;
import be.kuleuven.mume.query.QueryHelper;

import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.repackaged.org.json.JSONException;
import com.google.appengine.repackaged.org.json.JSONObject;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.RequestToken;

public class SigninServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6637360799707356074L;
	private static final Logger log = Logger.getLogger(SigninServlet.class.getName());
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		
		try{
			//Every Servlet must check whether the Persoon has already signed in.
			QueryHelper<PersoonBean> helper = PersoonQuery.getCurrentPersoonQuery("",false);
			PersoonBean persoon = helper.executeQuery();
			
			Twitter twitter = persoon.getTwitter();
			if (twitter != null) {
				try{
					//Try to login with local token
					twitter.verifyCredentials();
					JSONObject json = new JSONObject();
					json.put("result", "succes");
					resp.getWriter().write(json.toString());
					return;
				} catch(TwitterException t){
					log.log(Level.INFO,"TwitterException: Redirecting to TwitterAllowApp page", t);
				}
			}
			
			helper.close();
			
			String cont = req.getParameter("continue");
			if(cont == null || cont == "")
				//Where does the user want to go??
				//We all love google dont we?
				cont="www.google.com";
			
			//service will listen to twittercallback
			String scheme = req.getScheme();
			String serverName = req.getServerName();
			int serverPort = req.getServerPort();
			String callbackUrl = scheme + "://" + serverName + ":" + serverPort
					+ "/mobilenvi/twittercallback?continue=" + cont;
	
			twitter = new TwitterFactory().getInstance();
			twitter.setOAuthConsumer(TwitterConst.ConsumerKey,
					TwitterConst.ConsumerSecret);
	
			RequestToken requestToken;

		
			requestToken = twitter.getOAuthRequestToken(callbackUrl);

			DatastoreService datastore = DatastoreServiceFactory
					.getDatastoreService();
			UserService userService = UserServiceFactory.getUserService();
			String googleId = userService.getCurrentUser().getUserId();
			
			String token = requestToken.getToken();
			if(token == null||token == "")
				log.log(Level.SEVERE, "Leeg", "token is null");
			
			//cant store objects directly need to convert them to blob
			Entity rtoken = new Entity("OAuthTemp", token);
			rtoken.setProperty("rtoken", convertToBlob(requestToken));
			rtoken.setProperty("twitter", convertToBlob(twitter));
			rtoken.setProperty("UserId", googleId);

			//keep requestToken for creating the access token.
			datastore.put(rtoken);

			//redirect user to twitterlogin page
			//resp.sendRedirect(requestToken.getAuthorizationURL());
			JSONObject json = new JSONObject();
			json.put("link", requestToken.getAuthorizationURL());
			json.put("error","Pleas follow link to authorize Twitter");
			resp.getWriter().write(json.toString());

		} catch (TwitterException te) {
			if (401 == te.getStatusCode()) {
				log.log(Level.SEVERE,
						"Twitter: Unable to get the access token.",te);
			} else {
				log.log(Level.SEVERE, "Twitter Excption", te);
			}
		} catch(JSONException e){
			log.log(Level.SEVERE,"JSONException",e);
		} catch (UserNotLoggedInException e) {
			resp.getWriter().write(e.toJsonString());
		}
	}

	//Blob is some binary value.
	private Blob convertToBlob(Serializable o) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutput out = new ObjectOutputStream(bos);
		out.writeObject(o);
		Blob result = new Blob(bos.toByteArray());

		out.close();
		bos.close();

		return result;
	}
}
